package com.example.codereader;

import android.util.Log;

import java.util.ArrayList;

public class MyEAN {
    static private String[] code13A = {"0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"};
    //  even bit
    static private String[] code13B = {"0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111"};
    //  right bit
    static private String[] code13C = {"1110010", "1100110", "1101100", "1000010", "1011100", "1001110", "1010000", "1000100", "1001000", "1110100"};

    static private String[] decode13A = {"3211", "2221", "2122", "1411", "1132", "1231", "1114", "1312", "1213", "3112"};
    //  even bit
    static private String[] decode13B = {"1123", "1222", "2212", "1141", "2311", "1321", "4111", "2131", "3121", "2113"};


    static public String Encode(String inStr) {
        ArrayList<String> outCode = EncodeToList(inStr);
        if (outCode.size() != 0) {
            StringBuilder strB = new StringBuilder();
            for (String str :
                    outCode) {
                strB.append(str);
            }
            System.out.println(strB);
            return strB.toString();
        } else {
            return "Failed";
        }
    }

    static public ArrayList<String> EncodeToList(String inStr) {
        ArrayList<String> outCode = new ArrayList<>();

        inStr = "69" + inStr;
        inStr += CalculateCheckCode(inStr);
        char[] inCh = inStr.toCharArray();
        //  start: 101 (3
        outCode.add("f");
        outCode.add("v");
        outCode.add("f");

        //  left code (6
        outCode.add(code13A[inCh[1] - '0']);
        outCode.add(code13B[inCh[2] - '0']);
        outCode.add(code13B[inCh[3] - '0']);
        outCode.add(code13B[inCh[4] - '0']);
        outCode.add(code13A[inCh[5] - '0']);
        outCode.add(code13A[inCh[6] - '0']);

        //  middle: 01010 (5
        outCode.add("v");
        outCode.add("f");
        outCode.add("v");
        outCode.add("f");
        outCode.add("v");

        //  right code (6
        outCode.add(code13C[inCh[7] - '0']);
        outCode.add(code13C[inCh[8] - '0']);
        outCode.add(code13C[inCh[9] - '0']);
        outCode.add(code13C[inCh[10] - '0']);
        outCode.add(code13C[inCh[11] - '0']);
        outCode.add(code13C[inCh[12] - '0']);

        //  end: 101 (3
        outCode.add("f");
        outCode.add("v");
        outCode.add("f");

        //  total: 3+6+5+6+3=23
        return outCode;
    }

    static public String Decode(String[] inStr) {
        System.out.println("inStr size: " + inStr.length);
        ArrayList<Integer> outNum = new ArrayList<>();
        int left = 3, right = 14;
        if (inStr.length == 23) {
            if (inStr[0] == "f" && inStr[1] == "v" && inStr[2] == "f" &&
                    inStr[9] == "v" && inStr[10] == "f" && inStr[11] == "v" && inStr[12] == "f" && inStr[13] == "v" &&
                    inStr[20] == "f" && inStr[21] == "v" && inStr[22] == "f") {
                //  left num
                outNum.add(FindA(inStr[left]));
                outNum.add(FindB(inStr[left + 1]));
                outNum.add(FindB(inStr[left + 2]));
                outNum.add(FindB(inStr[left + 3]));
                outNum.add(FindA(inStr[left + 4]));
                outNum.add(FindA(inStr[left + 5]));
                //  right num
                for (int i = right; i < right + 6; i++) {
                    outNum.add(FindC(inStr[i]));
                }
            }
            outNum.add(0, CalculateLocalCode(outNum));
            System.out.println("outNum size: " + outNum.size());
            //  to string
            StringBuilder strB = new StringBuilder();
            for (Integer num :
                    outNum) {
                strB.append(num);
            }
            System.out.println(strB);
            return strB.toString();
        }
        return "Failed";
    }

    static private int FindA(String str) {
        for (int i = 0; i < code13A.length; i++) {
            if (code13A[i].equals(str)) return i;
        }
        return -1;
    }

    static private int FindB(String str) {
        for (int i = 0; i < code13A.length; i++) {
            if (code13B[i].equals(str)) return i;
        }
        return -1;
    }

    static private int FindC(String str) {
        for (int i = 0; i < code13A.length; i++) {
            if (code13C[i].equals(str)) return i;
        }
        return -1;
    }

    static private String CalculateCheckCode(String inStr) {
        char[] inCh = inStr.toCharArray();
        // 698208180301 = 108
        //  9 2 8 8 3 1 -> 31*3=93 (weight of odd is 3)
        // 6 8 0 1 0 0 ? = 15
        // ? = (10 - 108 % 10) % 10 = 2
        int sum = 0;
        for (int i = 0, len = inStr.length(); i < len; i++) {
            if (i % 2 == 0) {
                sum += (inCh[i] - '0');
            } else {
                sum += (inCh[i] - '0') * 3;
            }
        }
        int checkCode = (10 - sum % 10) % 10;
        return Integer.toString(checkCode);
    }

    static private int CalculateLocalCode(ArrayList<Integer> numbs) {
        int sum = 0;
        for (int i = 0, len = numbs.size(); i < len; i++) {
            if (i % 2 == 0) {
                sum += numbs.get(i) * 3;
            } else {
                sum += numbs.get(i);
            }
        }
        return 10 - sum % 10;
    }

}
